一、前言:函數不只是功能,更是語言的核心構件
在 JavaScript 中,函數的角色遠不僅止於封裝程式邏輯,它是語言中的一等公民(First-class Citizen)。這代表函數本身可以被賦值給變數、作為參數傳遞,甚至作為其他函數的返回值。本篇文章將由淺入深,帶您系統性地理解 JavaScript 中函數的結構、行為與核心特性。
在本文末會說明何謂一等公民
二、函數的基礎概念:語法、參數與引數
2.1 基本語法與調用方式
在 JavaScript 中,最基本的函數定義方式如下:
javascript複製編輯function functionName(parameter1, parameter2) {
// 函數主體
}
functionName為函數名稱,可用於之後的調用。parameter1,parameter2是定義階段的參數,用於接收外部傳入的資料。
範例如下:
javascript複製編輯function hello(name, message) {
console.log("Hello " + name + ", " + message);
}
hello("Leo Shiang", "How are you?");
2.2 「參數」與「引數」的差異
雖然「參數」(Parameter)與「引數」(Argument)常被混用,但兩者在概念上是不同的:
參數:定義函數時括號中宣告的變數名稱。
引數:實際呼叫函數時傳入的值。
JavaScript 對於引數數量與型態非常寬容:
可以傳入比定義時更多或更少的引數;多餘者會被忽略,未給值者為
undefined。傳入的資料型態不會受限於參數預期型別。
三、深入函數內部:返回值與 arguments 物件
3.1 函數的返回機制
函數可選擇是否使用 return 陳述式返回值:
javascript複製編輯function sum(a, b) {
return a + b;
}
若未使用 return,函數預設回傳 undefined:
javascript複製編輯function sum(a, b) {
// 無回傳值
}
console.log(sum(1, 2)); // 輸出 undefined
3.2 arguments 物件介紹
在傳統函數中(非箭頭函數),可以透過 arguments 物件存取所有傳入的引數。其特性包括:
類陣列物件,具有
length屬性與索引存取方式,但並非真正的陣列。可透過
arguments.length獲取傳入引數數量。在非嚴格模式下,
arguments與命名參數是雙向連動的。
範例一:取得引數數量
javascript複製編輯function howManyArgs() {
console.log(arguments.length);
}
howManyArgs("beauty", "of", "javascript"); // 3
範例二:與命名參數的連動
javascript複製編輯function add(a, b) {
arguments[1] = 10;
return a + b; // b 會被修改為 10
}
console.log(add(1, 2)); // 輸出 11
注意:在嚴格模式下 (
'use strict'),arguments與參數之間的連動關係已被取消。
四、函數的本質:可以傳遞的物件
JavaScript 中,函數實際上是 Function 類別的實例。作為物件,它們:
可以擁有自己的屬性與方法。
可以被賦值、傳遞,甚至回傳。
函數名稱實際上是一個指向函數物件的參考。
以下範例說明此特性:
javascript複製編輯function sum(a, b) {
return a + b;
}
var total = sum;
console.log(total(1, 2)); // 3
sum = null;
console.log(total(1, 2)); // 仍然可執行,輸出 3
五、函數的兩種定義方式:宣告與表示式
5.1 函數宣告(Function Declaration)
使用 function 關鍵字直接定義,具備提升(Hoisting)特性:
javascript複製編輯function sum(a, b) {
return a + b;
}
5.2 函數表示式(Function Expression)
將匿名函數賦值給變數:
javascript複製編輯var sum = function(a, b) {
return a + b;
};
5.3 差異說明:Hoisting
函數宣告會被提升:可在宣告前呼叫。
函數表示式僅提升變數名稱:賦值部分不會被提升。
範例如下:
javascript複製編輯console.log(sum(1, 2)); // 可正常執行
function sum(a, b) {
return a + b;
}
javascript複製編輯console.log(sum(1, 2)); // TypeError: sum is not a function
var sum = function(a, b) {
return a + b;
};
六、高階應用:函數作為一等公民的實例
函數可作為其他函數的引數或返回值,此能力稱為「高階函數」(Higher-Order Function):
javascript複製編輯function callFunction(fn, value) {
return fn(value);
}
function add10(num) {
return num + 10;
}
function greeting(name) {
return "Hello, " + name;
}
console.log(callFunction(add10, 5)); // 15
console.log(callFunction(greeting, "Leo")) // Hello, Leo
這種設計在現代 JavaScript 開發中極為常見,尤其是在 Promise、事件處理、以及 React 等框架中的函數組件與 Hooks 機制中。
七、補充說明:何謂一等公民?
當一個語言的某種元素被稱為「一等公民」(First-Class Citizen 或 First-Class Object),意思是:它在語言中被當作普通值來處理,具備與其他資料型別(如數字、字串、物件)相同的操作彈性與地位。
在 JavaScript 中,函數就是一等公民,這代表:
可以賦值給變數
const sayHi = function() { console.log("Hi"); };可以作為引數傳遞給其他函數
function call(fn) { fn(); } call(sayHi);可以作為函數的返回值
function createLogger(msg) { return function() { console.log(msg); }; } const logHello = createLogger("Hello"); logHello(); // 輸出 Hello可以擁有屬性和方法(因為函數也是物件)
function greet() {} greet.description = "這是一個問候函數"; console.log(greet.description); // "這是一個問候函數"
八、結語
函數是 JavaScript 的核心概念之一,不僅具備高度彈性,更是許多進階應用的基礎。透過理解函數的語法結構、參數傳遞方式,以及其作為一等公民的特性,能有效提升開發效率與程式碼可讀性。
無論是日常開發或框架應用,熟悉函數的本質與運作邏輯,都是成為優秀 JavaScript 開發者不可或缺的一步。希望本文能為您打下穩固的起點。